概述
在微服务架构中,一个系统划分为多个服务,每个服务有各自的配置,Spring Cloud Config提供了集中管理服务配置的功能,并且可以在服务运行时动态调整配置,而不需要重启服务。
Spring Cloud Config包括Config Server和Config Client两部分。
Config Server是一个可横向扩展、集中式的配置服务器,默认使用Git存储配置内容,本篇中也将使用Git存储各服务的配置。
Config Client即为各个微服务。在服务启动时,会向Config Server请求所需的配置属性,并缓存在本地使用。
构建Config Server
创建Github配置仓库
在github创建一个配置仓库 spring-cloud-demo-config,并创建config-client-dev.yml,内容如下:
config-client-dev.yml:
1 | routes: "{'user-ms': '/u/**', 'role-ms': '/r/**'}" |
可以看到在这个配置文件中我们写入了一些服务网关的路由规则,当然也可以添加一些其他的配置,这里只是作为一个例子。
创建config-server项目
config-server作为配置中心,本身也是一个服务,因此也可以注册到服务注册中心中。在创建config-server项目时,勾选Eureka Discovery和Config Server两个依赖,创建成功的项目中将包括如下依赖:
1 | <dependencies> |
编写配置文件,添加git仓库的地址和服务注册配置,如下:
1 | server: |
如果是私有项目的话,还需要在git节点下配置username和password。
修改config-server启动类,添加@EnableConfigServer和@EnableEurekaClient注解,如下:
1 |
|
这样,config-server配置中心就构建完成了。
测试访问配置数据
我们可以在config-server通过http请求访问git仓库的配置数据,访问规则如下:
- /{name}/{profile}[/{label}]
- /{name}-{profile}.yml
- /{label}/{name}-{profile}.yml
- /{name}-{profile}.properties
- /{label}/{name}-{profile}.properties
name:表示服务名称,如user-ms、role-ms
profile:表示config-client配置的profile,如dev、test、prod等
label:表示git仓库的分支
例如我们可以通过访问 http://localhost:8805/config-client/dev/master 来获取github仓库中config-client-dev.yml的配置内容
构建Config Client
添加依赖
创建一个名为config-client的工程来进行测试,由于我们在配置中心配置的是一些路由规则,这里的config-client就以zuul服务网关为例进行测试。
首先,为config-client工程添加如下依赖:
1 | <dependency> |
配置bootstrap.yml
bootstrap.yml用于配置config数据的拉取,在resources目录下新建bootstrap.yml,之所以使用bootstrap.yml而不是application.yml,是因为我们的配置数据大多是用来配置IOC容器的,而bootstrap.yml会在IOC容器启动前加载,以此可以实现配置数据的远端加载,bootstrap.yml内容如下:
1 | spring: |
这里有一点需要注意,前面的内容中,我们将config-server注册到了eureka-server,因此我们可以从eureka-server来发现config-server服务,然后拉取配置数据。如果没有将config-server注册到eureka-server,则可以直接在uri节点指定config-server的地址。
配置application.yml
1 | server: |
可以看到,我们没有为config-client配置路由规则。
创建配置类
首先,创建一个RouteProperty类,用于接收从config-server拉取的配置数据,如下所示:
1 |
|
@Value注解中的Key对应Github配置仓库中配置文件中的key。
然后,创建一个自定义的RouteLocator,用于手动注册路由规则,如下:
1 | public class CustomRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator { |
最后,创建Zuul路由规则的配置类,将我们自定义的RouteLocator注入IOC容器中,代码如下:
1 |
|
这样,我们就实现了从config-server拉取Zuul的路由规则,并应用于config-client服务中。
测试配置数据拉取
按顺序启动 eureka-server、config-server、config-client、user-ms、role-ms
可以看到user-ms在启动时会向config-server拉取配置信息
而且我们可以通过在配置中心中配置的路由规则来访问user-ms和role-ms
动态配置更新
在一些情况下,我们可能需要对线上的服务进行配置修改,但我们在Git仓库修改配置信息后,config-server可以读取到新的配置,而config-client(各微服务)由于在本地缓存了配置而无法动态更新配置信息,我们可以借助Actuator实现在不重启服务的情况下更新服务的配置,下面对config-client进行一些改造,让它支持动态配置更新。
配置Actuator
Actuator可以帮助我们监控和管理Spring Boot应用,并通过一些HTTP端点来进行健康检查、统计等操作。
为user-ms添加如下依赖:
1 | <dependency> |
修改application.yml,添加如下配置:
1 | management: |
上面的配置表示向外部暴露/actuator/refresh和/actuator/health接口,我们可以通过/actuator/refresh来通知client更新配置。
添加@RefreshScope注解
@RefreshScope注解是实现动态配置更新的重要注解。
当我们调用/actuator/refresh时,springboot会用新配置创建一个新的IOC容器,然后与原IOC容器的配置进行比较,找出那些修改了的配置,然后使用新配置重新创建由@RefreshScope注解的Bean。
修改RouteProperty类和ZuulConfig类,如下:
1 |
|
1 |
|
这里有一点需要注意,@RefreshScope注解不应与@Configuration注解同时使用,官方给出的说明是同时使用会出现意想不到的情况,@RefreshScope应当标注在那些需要重新创建的Bean上。
OK,到这里,动态配置更新就完成了,下面简单测试一下。
测试配置更新
首先,按照配置中心配置的路由规则来发送一次请求,如下所示:
然后,将github中的config-client-dev.yml内容修改为:
1 | routes: "{'user-ms': '/user/**', 'role-ms': '/role/**'}" |
调用refresh端点通知config-client刷新配置,如下所示:
再然后,我们依然按照原来的方式发送请求,就出现404错误,如下:
最后,我们按照修改后的规则来进行调用,如下所示:
可以看到,config-client的路由规则已经发生了改变。
通常,我们会在配置修改后自动通知config-client刷新配置,这可以借助消息队列来实现,我们在这里就先不去实验了。
源码地址:https://github.com/GreedyStar/spring-cloud-demo
最后的最后,安利一下自己写的一个Java代码生成工具,能够方便的生成Spring、SpringMVC、Mybatis架构下的Java代码,希望能对大家有所帮助,地址:Java代码生成器:Generator